#pragma once
class CTangoThreadPool : public CThreadPool
{
public:
	CTangoThreadPool(JetByteTools::Win32::CNamedIndex &userDataSlots,
		size_t initialThreads,
		size_t minThreads,
		size_t maxThreads,
		size_t maxDormantThreads,
		size_t poolMaintPeriod,
		size_t dispatchTimeout,
		size_t maxThreadsDispatchTimeout,
		size_t m_numReads,
		bool usingSequenceNumbers,
		bool useMultipleWrites);
	void DispatchConnectionEstablished(
		JetByteTools::Win32::CSocketServer::Socket *pSocket,
		JetByteTools::Win32::CIOBuffer *pAddress);

	void DispatchConnectionClosing(
		JetByteTools::Win32::CSocketServer::Socket *pSocket);

	void DispatchReadCompleted(
		JetByteTools::Win32::CSocketServer::Socket *pSocket,
		JetByteTools::Win32::CIOBuffer *pBuffer);

	void OnSocketReleased(
		JetByteTools::Win32::CSocketServer::Socket *pSocket);

	enum DispatchEvents
	{
		ConnectionEstablished,
		ConnectionClosing,
		ReadCompleted
	};

	class CPerConnectionData
	{
	public:

		CPerConnectionData();

		void SetAddress(
			const JetByteTools::Win32::_tstring &address);


		void UseConnection();

		JetByteTools::Win32::_tstring GetConnectionDetails() const;

	private:

		JetByteTools::Win32::CCriticalSection m_crit;

	public:

		JetByteTools::Win32::CIOBuffer::InOrderBufferList m_outOfSequenceReads;

	private:

		long m_numUses;

		JetByteTools::Win32::_tstring m_address;

		// No copies, do not implement
		CPerConnectionData(const CPerConnectionData &rhs);
		CPerConnectionData &operator=(const CPerConnectionData &rhs);
	};

	CPerConnectionData *GetPerConnectionData(
		JetByteTools::Win32::CSocketServer::Socket *pSocket) const;

	const size_t m_numReads;

	const bool m_usingSequenceNumbers;

	const bool m_useMultipleWrites;

private:

	void DoDispatch(
		JetByteTools::Win32::CSocketServer::Socket *pSocket,
		JetByteTools::Win32::CIOBuffer *pBuffer,
		DispatchEvents event);

	virtual void OnThreadStarted();
	virtual void OnThreadInitialised();
	virtual void OnProcessingStarted();
	virtual void OnReceivedMessage();
	virtual void OnProcessingStopped();
	virtual void OnThreadStopped();

	virtual JetByteTools::Win32::CThreadPool::WorkerThread *CreateWorkerThread(
		JetByteTools::Win32::CIOCompletionPort &iocp,
		JetByteTools::Win32::CEvent &messageReceivedEvent,
		JetByteTools::Win32::CThreadPool &pool);

	const size_t m_userDataIndex;

	// No copies do not implement
	CTangoThreadPool(const CTangoThreadPool &rhs);
	CTangoThreadPool &operator=(const CTangoThreadPool &rhs);
};

